package com.modulemanager.module

import android.util.Log
import com.libservice.RouteCompletion
import com.libservice.RouteResult
import com.modulemanager.ModuleManager
import com.modulemanager.handler.HandlerInterface
import com.modulemanager.models.PageConfig
import com.modulemanager.page.PageInterface

open class Module(
    override val type: String,
    override val id: String?,
    private val pageBuilders: MutableList<PageInterface.Builder>,
    private val handlerBuilders: MutableList<HandlerInterface.Builder>? = null
) : ModuleInterface {
    companion object {
        private const val TAG: String = "Module"
    }

    private val pages: MutableList<PageInterface> = mutableListOf()

    private val handlers: MutableList<HandlerInterface> = mutableListOf()

    override fun page(
        type: String?,
        id: String?,
        config: PageConfig?,
        params: Map<String, Any>?,
        hash: String?
    ): PageInterface? {
        val pageBuilder =
            pageBuilders.firstOrNull { pageBuilder -> type == null || pageBuilder.type == type }
                ?: return null

        var page = pages.firstOrNull { page ->
            page.type == pageBuilder.type && page.id == id
        }

        if (page != null) {
            return page
        }

        page = pageBuilder.build(this, id, config, params, hash)
        if (page != null) {
            pages.add(page)
        }

        return page
    }

    override fun removePage(type: String, id: String?) {
        pages.removeAll { it.type == type && it.id == id }

        Log.i(TAG, "Remove page type: ${type}, id: ${id ?: "null"}")
        Log.i(TAG, "Page count: ${pages.size}")

        if (pages.size == 0) {
            ModuleManager.instance.removeModule(this.type, this.id)
        }
    }

    override fun handle(type: String?, params: Map<String, Any>?, completion: RouteCompletion?) {
        val handlerBuilder: HandlerInterface.Builder? =
            handlerBuilders?.firstOrNull { handlerBuilder ->
                type == null || handlerBuilder.type == type
            }

        if (handlerBuilder == null) {
            completion?.let { it(RouteResult.ERROR, null) }
            return
        }

        val handler = handlerBuilder.build(this)
        handlers.add(handler)

        handler.handle(params) { result, resultParam ->
            completion?.let { it(result, resultParam) }
            handlers.remove(handler)
        }
    }
}